package com.hfjyz.registration.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.bind.JAXB;

import com.hfjyz.registration.model.OrderInfo;
import com.hfjyz.registration.pay.icbc.search.api.ICBCAPI;
import com.hfjyz.registration.pay.icbc.search.api.OutType;

public class OrderPaySearchFromBank {

	// ++++++++++++++++++++++++++++++++
	private static String getPlainReqData(OrderInfo o, ExamProperties properties) {
		boolean isDebug = properties.isDebug();
		String tranDate = o.getOrderDate().substring(0, 8);
		if (isDebug) {
			DateFormat format2 = new SimpleDateFormat("yyyyMMdd");
			tranDate = format2.format(new Date());
		}
		String data = 
				"<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"no\" ?>"
				+ "<ICBCAPI>"
					+ "<in>"
						+ "<orderNum>" + o.getId() + "</orderNum>"
						+ "<tranDate>" + tranDate + "</tranDate>"
						+ "<ShopCode>" + properties.getPayMerID() + "</ShopCode>"
						+ "<ShopAccount>" + properties.getPayMerAcct() + "</ShopAccount>"
					+ "</in>"
				+ "</ICBCAPI>";
		return data;
	}

	
	/**
	 * @param o
	 * @param properties
	 * @return 0: 查询成功  1: 查询失败 2: 订单未找到
	 */
	public static int getBankResult(OrderInfo o, ExamProperties properties) {
		try {
			String getPlainReqData = getPlainReqData(o, properties);
			String sendmsg = "APIName=EAPI" + "&APIVersion=001.001.002.001"
					+ "&MerReqData="
					+ URLEncoder.encode(getPlainReqData, "GBK");

			SSLSocketFactory ssf = null;
			PrintWriter out = null;
			BufferedReader in = null;
			String pass = properties.getSearchKeyPass();

			try {
				SSLContext ctx = SSLContext.getInstance("TLS");
				KeyManagerFactory kmf = KeyManagerFactory
						.getInstance("SunX509");
				// TrustManagerFactory tmf =
				// TrustManagerFactory.getInstance("SunX509");
				KeyStore ks = KeyStore.getInstance("PKCS12");

				// load keystore
				ks.load(new FileInputStream(properties.getSearchPfxPath()),
						pass.toCharArray());
				kmf.init(ks, pass.toCharArray());
				ctx.init(kmf.getKeyManagers(), trustAllCerts, null);

				ssf = ctx.getSocketFactory();
				HttpsURLConnection.setDefaultSSLSocketFactory(ssf);
				HttpsURLConnection.setDefaultHostnameVerifier(hnv);
				URL realUrl = new URL(properties.getSearchBankURL());

				// 打开和URL之间的连接
				HttpsURLConnection conn = (HttpsURLConnection) realUrl
						.openConnection();

				// 设置通用的请求属性
				conn.setRequestProperty("accept", "*/*");
				conn.setRequestProperty("connection", "Keep-Alive");
				conn.setRequestProperty("User-Agent",
						"Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

				// 发送POST请求必须设置如下两行
				conn.setDoOutput(true);
				conn.setDoInput(true);
				// 获取URLConnection对象对应的输出流
				out = new PrintWriter(conn.getOutputStream());
				// 发送请求参数
				out.print(sendmsg);
				// flush输出流的缓冲
				out.flush();
				// 定义BufferedReader输入流来读取URL的响应
				in = new BufferedReader(new InputStreamReader(
						conn.getInputStream()));
				String line;
				String strresult = "";
				while ((line = in.readLine()) != null) {
					strresult += line;
				}
				if (strresult.length() == 5) {
//					if ("40972".equals(strresult)) {
						return 2;
//					}
//					String errorString = getErrorMsg(strresult);
//					throw new Exception(errorString);
				}
				strresult = URLDecoder.decode(strresult, "GBK").trim();
				if (strresult.contains("ICBCAPI")) {
					strresult = strresult
							.replace("<ICBCAPI>",
									"<ICBCAPI xmlns=\"http://registration.hfjyz.com/pay/icbc/search/api\">");
				}
				ICBCAPI type = JAXB.unmarshal(new StringReader(strresult),
						ICBCAPI.class);
				OutType outType = type.getOut();
				updateOrderInfoByBankResult(o, outType);
				return ("0".equals(outType.getTranStat()) || "1".equals(outType
						.getTranStat())) ? 0 : 1;
			} catch (Exception e) {
				e.printStackTrace();
				return 1;
			} finally { // 使用finally块来关闭输出流、输入流
				try {
					if (out != null) {
						out.close();
					}
					if (in != null) {
						in.close();
					}
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return 1;
		}
	}

	private static String getErrorMsg(String code) {
		String errorString = "";

		if ("40972".equals(code)) {
			errorString = "API查询的订单不存在";
		} else if ("40973".equals(code)) {
			errorString = "API查询过程中系统异常";
		} else if ("40976".equals(code)) {
			errorString = "API查询系统异常";
		} else if ("40977".equals(code)) {
			errorString = "商户证书信息错";
		} else if ("40978".equals(code)) {
			errorString = "解包商户请求数据报错";
		} else if ("40980".equals(code)) {
			errorString = "API查询过程中系统异常";
		} else if ("40981".equals(code)) {
			errorString = "给商户打包返回数据错";
		} else if ("40982".equals(code)) {
			errorString = "系统错误";
		} else if ("40983".equals(code)) {
			errorString = "查询的订单不唯一";
		} else if ("40987".equals(code)) {
			errorString = "请求数据中接口名错误";
		} else if ("40947".equals(code)) {
			errorString = "商户代码或者商城账号有误";
		} else if ("40948".equals(code)) {
			errorString = "商城状态非";
		} else if ("40949".equals(code)) {
			errorString = "商城类别非法";
		} else if ("40950".equals(code)) {
			errorString = "商城应用类别非法";
		} else if ("40951".equals(code)) {
			errorString = "商城应用类别非法";
		} else if ("40952".equals(code)) {
			errorString = "商户证书id未绑定";
		} else if ("40953".equals(code)) {
			errorString = "商户id权限非法";
		} else if ("40954".equals(code)) {
			errorString = "检查商户状态时数据库异常";
		}
		return code + ":" + errorString;
	}

	private static int updateOrderInfoByBankResult(OrderInfo o, OutType outType)
			throws Exception {
		int result = 0;
		if ("0".equals(outType.getTranStat())
				|| "1".equals(outType.getTranStat())) {
			o.setOrderState(1); // 支付成功
		} else {
			o.setOrderState(2); // 支付失败
			result = 2;
		}
		o.setTranSerialNum(outType.getTranSerialNum());
		o.setTranStat(outType.getTranStat());
		o.setBankRem(outType.getBankRem());
		o.setAmount(outType.getAmount());
		o.setCurrType(outType.getCurrType());
		o.setTranTime(outType.getTranTime());
		o.setShopAccount(outType.getShopAccount());
		o.setPayeeName(outType.getPayeeName());
		o.setJoinFlag(outType.getJoinFlag());
		o.setMerJoinFlag(outType.getMerJoinFlag());
		o.setCustJoinFlag(outType.getCustJoinFlag());
		o.setCustJoinNum(outType.getCustJoinNum());
		o.setCertID(outType.getCertID());
		return result;
	}

	/**
	 * 所有主机默认通过
	 */
	private static HostnameVerifier hnv = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	/**
	 * 关键在这信任所有证书
	 */
	private static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		public void checkServerTrusted(X509Certificate[] certs, String authType) {
			return;
		}

		public void checkClientTrusted(X509Certificate[] certs, String authType) {
			return;
		}
	} // X509TrustManager
	};
}
